#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#include <OneButton.h>
#include <FastLED.h>

// How many leds in your strip?
#define NUM_LEDS 1
#define DATA_PIN 8

// Define the array of leds
CRGB leds[NUM_LEDS];

// 定义服务和特征UUID
#define SERVICE_UUID        "00001812-0000-1000-8000-00805f9b34fb" // 完整的128位UUID
#define CHARACTERISTIC_UUID "00002a4d-0000-1000-8000-00805f9b34fb"

// 定义命令
#define CMD_UP         0x01
#define CMD_DOWN       0x02
#define CMD_BACK       0x03
#define CMD_CONFIRM    0x04
#define CMD_SLEEP      0x05
#define CMD_SHUTDOWN   0x06
#define CMD_REMOTE_OFF 0x07

// 定义按键引脚
#define BUTTON_1 0
#define BUTTON_UP_PIN   1
#define BUTTON_DOWN_PIN 20

BLEServer *pServer;
BLEService *pService;
BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
BLEAdvertising *pAdvertising;

// 创建按键对象
OneButton button1(BUTTON_1, true);
OneButton buttonUp(BUTTON_UP_PIN, true);
OneButton buttonDown(BUTTON_DOWN_PIN, true);

// 服务器回调类
class MyServerCallbacks : public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("设备已连接");
    }

    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("设备已断开连接");
      // 重启广播
      pAdvertising->start();
      Serial.println("重新开始广播，等待客户端连接...");
    }
};


// 发送BLE命令函数
void sendBLECommand(uint8_t command) {
  if (deviceConnected && pCharacteristic) {
    pCharacteristic->setValue(&command, 1);
    pCharacteristic->notify();
    Serial.print("发送命令: 0x");
    Serial.println(command, HEX);
  } else {
    Serial.println("设备未连接，无法发送命令");
  }
}

void button1Click(){
  sendBLECommand(CMD_CONFIRM);
}

void button1DoubleClick(){
  sendBLECommand(CMD_BACK);
}

void button1LongClick(){
  sendBLECommand(CMD_SHUTDOWN);
}

// 按键回调函数
void onUpButtonClick() {
  Serial.println("上翻页按键单击");
  sendBLECommand(CMD_UP);
}

void onDownButtonClick() {
  Serial.println("下翻页按键单击");
  sendBLECommand(CMD_DOWN);
}

void setup() {
  Serial.begin(115200);
  Serial.println("启动ESP32-C6 BLE GATT服务...");
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  // 开机闪两次红灯
  leds[0] = CRGB::Red;
  FastLED.show();
  delay(300);
  leds[0] = CRGB::Black;
  FastLED.show();
  delay(300);
  leds[0] = CRGB::Red;
  FastLED.show();
  delay(300);
  leds[0] = CRGB::Black;
  FastLED.show();
  delay(300);

  // 初始化BLE设备
  BLEDevice::init("RC-X4");
  Serial.println("BLE设备初始化完成");

  // 创建BLE服务器
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());
  Serial.println("BLE服务器创建完成");

  // 创建BLE服务
  pService = pServer->createService(SERVICE_UUID);
  Serial.println("BLE服务创建完成");

  // 创建BLE特征 - 确保设置了正确的属性
  pCharacteristic = pService->createCharacteristic(
                      CHARACTERISTIC_UUID,
                      BLECharacteristic::PROPERTY_READ |
                      BLECharacteristic::PROPERTY_WRITE |
                      BLECharacteristic::PROPERTY_NOTIFY |
                      BLECharacteristic::PROPERTY_INDICATE
                    );
  Serial.println("BLE特征创建完成");

  // 添加描述符 - 这是启用通知/指示所必需的
  pCharacteristic->addDescriptor(new BLE2902());
  Serial.println("描述符添加完成");
  
  // 设置特征的初始值
  uint8_t initialValue[1] = {0};
  pCharacteristic->setValue(initialValue, 1);
  
  // 启动服务
  pService->start();
  Serial.println("BLE服务已启动");

  // 配置广播数据
  pAdvertising = BLEDevice::getAdvertising();
  
  // 确保服务UUID包含在广播数据中
  pAdvertising->addServiceUUID(SERVICE_UUID);
  
  // 设置扫描响应数据
  BLEAdvertisementData scanResponseData;
  scanResponseData.setName("X4翻页器");
  scanResponseData.setCompleteServices(BLEUUID(SERVICE_UUID));
  pAdvertising->setScanResponseData(scanResponseData);
  
  // 设置广播参数
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);
  pAdvertising->setMaxPreferred(0x12);
  
  // 开始广播
  pAdvertising->start();
  Serial.println("BLE广播已开始，等待客户端连接...");
  Serial.print("服务UUID: ");
  Serial.println(SERVICE_UUID);
  Serial.print("特征UUID: ");
  Serial.println(CHARACTERISTIC_UUID);

  // 初始化按键
  buttonUp.attachClick(onUpButtonClick);
  buttonDown.attachClick(onDownButtonClick);
  button1.attachClick(button1Click);
  button1.attachDoubleClick(button1DoubleClick);
  button1.attachLongPressStop(button1LongClick);
  Serial.println("按键初始化完成");
}

void loop() {
  // 处理按键事件
  button1.tick();
  buttonUp.tick();
  buttonDown.tick();
  
  // 定期检查连接状态
  static unsigned long lastCheck = 0;
  if (millis() - lastCheck > 5000) {
    lastCheck = millis();
    if (!deviceConnected) {
      Serial.println("等待客户端连接...");
    }
  }
  
  delay(10);
}